package com.yoso.core.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.format.FastDateFormat;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import lombok.Data;
import lombok.experimental.Accessors;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 日期工具
 * @author shizejin
 * @date 2023/11/28 09:58
 */
public class DateUtil {

    /**
     * yyyy-MM-dd -> yyyyMMdd
     */
    public static String parseMiniDate(String dateStr) {
        return convertDateStr(dateStr, DatePattern.NORM_DATE_PATTERN, DatePattern.PURE_DATE_PATTERN);
    }

    /**
     * yyyyMMdd -> yyyy-MM-dd
     */
    public static String parseCommonDate(String dateStr) {
        return convertDateStr(dateStr, DatePattern.PURE_DATE_PATTERN, DatePattern.NORM_DATE_PATTERN);
    }

    /**
     * 日期格式相互转换
     * @param dateStr yyyyMMdd | yyyy-MM-dd
     * @param sourcePatten yyyyMMdd | yyyy-MM-dd
     * @param targetPatten yyyyMMdd | yyyy-MM-dd
     * @return 日期
     */
    public static String convertDateStr(String dateStr, String sourcePatten, String targetPatten) {
        Date formatDate = null;
        try {
            formatDate = FastDateFormat.getInstance(sourcePatten).parse(dateStr);
        } catch (Exception e) {
//            log("日期：{}格式失败，message:{}", dateStr, e.getMessage());
            return "";
        }
        return FastDateFormat.getInstance(targetPatten).format(formatDate);
    }

    /**
     * yyyy-MM-dd ->  yyyy-MM-dd HH:mm:ss
     */
    public static String convertDate2DateTime(String dateStr) {
        return convertDateStr(dateStr, DatePattern.NORM_DATE_PATTERN, DatePattern.NORM_DATETIME_PATTERN);
    }


    /**
     * 转换查询日期
     * ep: 2013-05-05 -> 2013-05-05 23:59:59
     * @param date 日期
     * @return {@link String } 日期时间
     * @author shizejin
     * @date 2023/11/16 15:51
     */
    public static String parseDateLastMoment(String date) {
        if (StrUtil.isBlank(date)) {
            return null;
        }
        DateTime dateTime = cn.hutool.core.date.DateUtil.parse(date);
//        加一天，减一秒
        DateTime offset = dateTime.offset(DateField.DAY_OF_YEAR, 1).offset(DateField.SECOND, -1);
        return cn.hutool.core.date.DateUtil.format(offset, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 合并日期区间
     * @param intervals
     * @return {@link List }<{@link DateInterval }>
     * @author shizejin
     * @date 2023/12/06 10:04
     */
    public static List<DateInterval> mergeDateInterval(List<DateInterval> intervals) {
        if (CollUtil.isEmpty(intervals)) {
            return Lists.newArrayList();
        }
        intervals = intervals.stream().sorted(Comparator.comparing(DateInterval::beginDate)).collect(Collectors.toList());

        for (int i = 0; i < intervals.size() - 1; i++) {
            intervals.get(i).setNext(intervals.get(i + 1));
        }
        DateInterval mergeInterval = CollUtil.getFirst(intervals);
        mergeDateInterval(mergeInterval);
        return recursionGet(mergeInterval);
    }

    /**
     * 合并日期区间
     * @param dateInterval
     * @author shizejin
     * @date 2023/12/06 10:04
     */
    private static void mergeDateInterval(DateInterval dateInterval) {
        if (dateInterval == null || dateInterval.getNext() == null) {
            return;
        }
        DateInterval next = dateInterval.getNext();
//        下一个区间的左区间落在当前区间，说明是可以合并的（日期有一天的间隔是连续的）
        if (!next.beginDate().isBefore(dateInterval.beginDate()) && !next.beginDate().isAfter(dateInterval.endDate().plusDays(1))) {
//            右区间取两者的最大，赋值给当前区间
            if (next.endDate().isAfter(dateInterval.endDate())) {
                dateInterval.setEndDate(next.getEndDate());
            }
//            合并完成，删除被合并的区间
            dateInterval.setNext(next.getNext());
//            向下合并
            mergeDateInterval(dateInterval);
        } else {
//            没有交集，下一个区间合并
            mergeDateInterval(next);
        }
    }

    /**
     * 获取链表中的所有数据
     * @param mergeInterval
     * @return {@link List }<{@link DateInterval }>
     * @author shizejin
     * @date 2023/12/06 10:04
     */
    private static List<DateInterval> recursionGet(DateInterval mergeInterval) {
        List<DateInterval> result = Lists.newArrayList();
        if (mergeInterval == null) {
            return result;
        }
        result.add(mergeInterval);
        CollUtil.addAll(result, recursionGet(mergeInterval.getNext()));
        return result;
    }


    @Data
    @Accessors(chain = true)
    public static class DateInterval {
        private String beginDate;
        private String endDate;
        private DateInterval next;

        private static final DateTimeFormatter dft = DateTimeFormatter.ofPattern("yyyyMMdd");

        public LocalDate beginDate() {
            return LocalDate.parse(getBeginDate(), dft);
        }
        public LocalDate endDate() {
            return LocalDate.parse(getEndDate(), dft);
        }
        @Override
        public String toString() {
            return "[" + beginDate + "," + endDate + "] " + Optional.ofNullable(next).map(DateInterval::toString).orElse("");
        }
    }

}
